package com.ngmaster.socket;

/**
 * 各种数值与Byte数组的转化
 *
 */
public class BitConverter {

	public static boolean IS_BIG_ENDIAN = true;

	/**
	 * 浮点数转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(float value) {
		int intBits = Float.floatToIntBits(value);
        return getBytes(intBits);
	}
	
	/**
	 * 浮点数转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(double value) {
        long longBits = Double.doubleToLongBits(value);
        return getBytes(longBits);
    }
	
	/**
	 * 长整形转化为字符串
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(long value) {
		byte[] bytes = new byte[8];
		if (IS_BIG_ENDIAN) {
			bytes[7] = (byte) (value & 0xff);
			bytes[6] = (byte) ((value >> 8) & 0xff);
			bytes[5] = (byte) ((value >> 16) & 0xff);
			bytes[4] = (byte) ((value >> 24) & 0xff);
			bytes[3] = (byte) ((value >> 32) & 0xff);
			bytes[2] = (byte) ((value >> 40) & 0xff);
			bytes[1] = (byte) ((value >> 48) & 0xff);
			bytes[0] = (byte) ((value >> 56) & 0xff);
		} else {
			bytes[0] = (byte) (value & 0xff);
			bytes[1] = (byte) ((value >> 8) & 0xff);
			bytes[2] = (byte) ((value >> 16) & 0xff);
			bytes[3] = (byte) ((value >> 24) & 0xff);
			bytes[4] = (byte) ((value >> 32) & 0xff);
			bytes[5] = (byte) ((value >> 40) & 0xff);
			bytes[6] = (byte) ((value >> 48) & 0xff);
			bytes[7] = (byte) ((value >> 56) & 0xff);
		}
        return bytes;
	}
	
	/**
	 * 整形转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(int value) {
        byte[] bytes = new byte[4];
        if (IS_BIG_ENDIAN) {
			bytes[3] = (byte) (value & 0xff);
			bytes[2] = (byte) ((value & 0xff00) >> 8);
			bytes[1] = (byte) ((value & 0xff0000) >> 16);
			bytes[0] = (byte) ((value & 0xff000000) >> 24);
		} else {
			bytes[0] = (byte) (value & 0xff);
			bytes[1] = (byte) ((value & 0xff00) >> 8);
			bytes[2] = (byte) ((value & 0xff0000) >> 16);
			bytes[3] = (byte) ((value & 0xff000000) >> 24);
        }
        return bytes;
    }
	
	/**
	 * 短整形转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(short value) {
		byte[] bytes = new byte[2];
		if (IS_BIG_ENDIAN) {
			bytes[1] = (byte) (value & 0xff);
			bytes[0] = (byte) ((value & 0xff00) >> 8);
		} else {
			bytes[0] = (byte) (value & 0xff);
			bytes[1] = (byte) ((value & 0xff00) >> 8);
		}
        return bytes;
	}
	
	/**
	 * 字符转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(char value) {
		byte[] bytes = new byte[2];
		if (IS_BIG_ENDIAN) {
			bytes[1] = (byte) (value);
			bytes[0] = (byte) (value >> 8);
		} else {
			bytes[0] = (byte) (value);
			bytes[1] = (byte) (value >> 8);
		}
        return bytes;
	}
	
	/**
	 * 字符转化为数组
	 * @param value
	 * @return
	 */
	public static byte[] getBytes(byte value) {
		byte[] bytes = new byte[1];
        bytes[0] = (byte) (value);
        return bytes;
	}
	
	/**
	 * 转化为浮点数
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static float toFloat(byte[] value, int startIndex) {
		return Float.intBitsToFloat(toInt(value, startIndex));
	}
	
	/**
	 * 转化为浮点数
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static double toDouble(byte[] value, int startIndex) {
        return Double.longBitsToDouble(toLong(value, startIndex));
	}
	
	/**
	 * 转化为Int64
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static long toLong(byte[] value, int startIndex) {
		if (IS_BIG_ENDIAN) {
			return (0xffL & (long) value[startIndex + 7])
					| (0xff00L & ((long) value[startIndex + 6] << 8))
					| (0xff0000L & ((long) value[startIndex + 5] << 16))
					| (0xff000000L & ((long) value[startIndex + 4] << 24))
					| (0xff00000000L & ((long) value[startIndex + 3] << 32))
					| (0xff0000000000L & ((long) value[startIndex + 2] << 40))
					| (0xff000000000000L & ((long) value[startIndex + 1] << 48))
					| (0xff00000000000000L & ((long) value[startIndex + 0] << 56));
		} else {
			return (0xffL & (long) value[startIndex + 0])
					| (0xff00L & ((long) value[startIndex + 1] << 8))
					| (0xff0000L & ((long) value[startIndex + 2] << 16))
					| (0xff000000L & ((long) value[startIndex + 3] << 24))
					| (0xff00000000L & ((long) value[startIndex + 4] << 32))
					| (0xff0000000000L & ((long) value[startIndex + 5] << 40))
					| (0xff000000000000L & ((long) value[startIndex + 6] << 48))
					| (0xff00000000000000L & ((long) value[startIndex + 7] << 56));
		}
	}
	
	/**
	 * 转化为数组
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static int toInt(byte[] value, int startIndex) {
		if (IS_BIG_ENDIAN) {
			return (0xff & value[startIndex + 3])
					| (0xff00 & (value[startIndex + 2] << 8))
					| (0xff0000 & (value[startIndex + 1] << 16))
					| (0xff000000 & (value[startIndex + 0] << 24));
		} else {
			return (0xff & value[startIndex + 0])
					| (0xff00 & (value[startIndex + 1] << 8))
					| (0xff0000 & (value[startIndex + 2] << 16))
					| (0xff000000 & (value[startIndex + 3] << 24));
		}
	}
	
	/**
	 * 转化为短整形
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static short toShort(byte[] value, int startIndex) {
		if (IS_BIG_ENDIAN) {
			return (short) ((0xff & value[startIndex + 1])
					| (0xff00 & (value[startIndex + 0] << 8)));
		} else {
			return (short) ((0xff & value[startIndex + 0])
					| (0xff00 & (value[startIndex + 1] << 8)));
		}
	}

	public static char toChar(byte[] value, int startIndex) {
		if (IS_BIG_ENDIAN) {
			return (char) ((0xff & value[startIndex + 1])
					| (0xff00 & (value[startIndex + 0] << 8)));
		} else {
			return (char) ((0xff & value[startIndex + 0])
					| (0xff00 & (value[startIndex + 1] << 8)));
		}
	}
	
	/**
	 * 转化为短整形
	 * @param value
	 * @param startIndex
	 * @return
	 */
	public static byte toByte(byte[] value, int startIndex) {
		return (byte) (0xff & value[startIndex]);
	}

	/**
	 * 十六进制字符串转换成二进制数组
	 * @param hex 十六进制的值，例如：89,去掉 0x
	 * */
	public static byte[] hexStringToByte(String hex) {
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] achar = hex.toCharArray();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
		}
		return result;
	}

	private static byte toByte(char c) {
		byte b = (byte) "0123456789abcdef".indexOf(c);
		return b;
	}

	/**
	 * 将二进制转换成不带0x的十六进制字符串
	 * */
	public static String bytesToHexString(byte[] src){
		StringBuilder stringBuilder = new StringBuilder();
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);

			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString().toUpperCase();
	}

	/**
	 * 将二进制转为16进制字符串,StringBuilder单线程安全,效率高(推荐)
	 * @param bytes
	 * @return
	 */
	public static String toHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02X", b));
		}
		return sb.toString();
	}
}
